package org.raymond.iworks.core.holder;

import lombok.extern.slf4j.Slf4j;
import org.raymond.iworks.commons.utils.ErrorUtil;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

@Slf4j
@Component
public class LockHolder {
    @Autowired
    private RedissonClient redisson;
    private ConcurrentNavigableMap bloomFilterRegister = new ConcurrentSkipListMap();

    /**
     * redisson 分布式锁
     * @param name
     * @return
     */
    public RLock lock(String name){
        RLock lock = null;
        try {
            lock = redisson.getLock(name);
        } catch(Exception e){
            log.error("{}", ErrorUtil.getErrorLog(e));
        }
        return lock;
    }

    /**
     * 全局限流器: rateInterval毫秒内允许通过rate流量
     * @param name 限流器名称
     * @param rate 限制流量
     * @param rateInterval 限制流量间隔时间(毫秒)
     * @return
     */
    public RRateLimiter rateLimiter(String name, long rate, long rateInterval){
        RRateLimiter rateLimiter = null;
        try {
            rateLimiter = redisson.getRateLimiter(name);
            rateLimiter.setRate(RateType.OVERALL, rate, rateInterval, RateIntervalUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("{}", ErrorUtil.getErrorLog(e));
        }
        return rateLimiter;
    }

    public <T> RBloomFilter<T> createBloomFilter(String name, long expectedInsertions, double falseProbability) {
        RBloomFilter<T> bloomFilter = null;
        try{
            bloomFilter = redisson.getBloomFilter(name);
            bloomFilter.tryInit(expectedInsertions, falseProbability);
        }catch(Exception e){
            log.error("{}", ErrorUtil.getErrorLog(e));
        }
        return bloomFilter;
    }

    public <T> RBloomFilter<T> getBloomFilter(String name) {
        RBloomFilter<T> bloomFilter = null;
        try{
            bloomFilter = redisson.getBloomFilter(name);
        }catch(Exception e){
            log.error("{}", ErrorUtil.getErrorLog(e));
        }
        return bloomFilter;
    }

    public <T> boolean addToBollmFilter(String name, T obj){
        RBloomFilter<T> bloomFilter = getBloomFilter(name);
        bloomFilter.add(obj);
        return false;
    }

    public <T> boolean addToBollmFilter(String name, Collection<T> collection){
        RBloomFilter<T> bloomFilter = getBloomFilter(name);
        bloomFilter.add(collection);
        return false;
    }
}
